package cn.com.myspring.framework.webmvc.servlet;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.com.myspring.framework.annotation.MYRequestParam;

public class MYHandlerAdapter {

    public boolean supports(Object handler) {
        return (handler instanceof MYHandlerMapping);
    }

    // 参数封装
    MYModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        MYHandlerMapping handlerMapping = (MYHandlerMapping) handler;

        // 把方法的形参列表和request的参数列表所在顺序进行一一对应
        // key:参数名 value:位置索引
        Map<String, Integer> paramIndexMapping = new HashMap<String, Integer>();

        // 把方法上的注解拿到，得到的是一个二维数组(一个参数有多个注解)
        Annotation[][] pa = handlerMapping.getMethod().getParameterAnnotations();
        for (int i = 0; i < pa.length; i++) {
            for (Annotation a : pa[i]) {
                if (a instanceof MYRequestParam) {
                    String paramName = ((MYRequestParam) a).value();
                    if (!"".equals(paramName.trim())) {
                        paramIndexMapping.put(paramName, i);
                    }
                }
            }
        }

        // 获取方法上的参数类型
        Class<?>[] paramsTypes = handlerMapping.getMethod().getParameterTypes();
        
        // 存储HttpServletRequest
        for (int i = 0; i < paramsTypes.length; i++) {
            Class<?> type = paramsTypes[i];
            if (type == HttpServletRequest.class || type == HttpServletResponse.class) {
                paramIndexMapping.put(type.getName(), i);
            }
        }

        // 获取通过HttpServletRequest传入的参数
        Map<String, String[]> params = request.getParameterMap();

        // 实参列表
        Object[] paramValues = new Object[paramsTypes.length];

        // 找寻方法形参位置,并赋值
        for (Map.Entry<String, String[]> parm : params.entrySet()) {
            // 将参数数组{"1","2","3"} 转成字符串 [1][2][3] 转成  1,2,3
            String value = Arrays.toString(parm.getValue()).replaceAll(" |\\[|\\]", "").replaceAll("\\s", ",");

            if (!paramIndexMapping.containsKey(parm.getKey())) {
                continue;
            }

            int index = paramIndexMapping.get(parm.getKey());
            paramValues[index] = caseStringValue(value, paramsTypes[index]);
        }

        if (paramIndexMapping.containsKey(HttpServletRequest.class.getName())) {
            int reqIndex = paramIndexMapping.get(HttpServletRequest.class.getName());
            paramValues[reqIndex] = request;
        }

        if (paramIndexMapping.containsKey(HttpServletResponse.class.getName())) {
            int respIndex = paramIndexMapping.get(HttpServletResponse.class.getName());
            paramValues[respIndex] = response;
        }

        // 调用Controller中的方法
        Object result = handlerMapping.getMethod().invoke(handlerMapping.getController(), paramValues);
        if (result == null || result instanceof Void) {
            return null;
        }

        boolean isModelAndView = handlerMapping.getMethod().getReturnType() == MYModelAndView.class;
        if (isModelAndView) {
            return (MYModelAndView) result;
        }
        return null;
    }

    // 类型转换-可以采用策略模式进行优化
    private Object caseStringValue(String value, Class<?> paramsType) {
        if (String.class == paramsType) {
            return value;
        }
        // 如果是int
        if (Integer.class == paramsType) {
            return Integer.valueOf(value);
        } else if (Double.class == paramsType) {
            return Double.valueOf(value);
        } else {
            if (value != null) {
                return value;
            }
            return null;
        }
    }
    
}
